#include "drv_iic.h"
#include "drv_systick.h"


//SCL->PC6
//SDA->PC7
void drv_iic_init(void)//IIC1_SDA->PB7,IIC1_SCL->PB6
{
	GPIO_InitTypeDef GPIO_InitStruct;
		
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}
void drv_iic_in(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void drv_iic_out(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void drv_iic_start(void)
{
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_out();//将数据线设置为输出模式

	SDA_H;//将数据线拉高
	SCL_H;//拉高时钟线，使数据有效
	drv_systick_us(5);//>4.7us，延时5us，满足IIC时序要求
	SDA_L;//拉低数据线，产生下降沿
	drv_systick_us(5);//>4us，延时5us，满足IIC时序要求
	SCL_L;//拉低时钟线占用总线
}
void drv_iic_stop(void)
{
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_out();//将数据线设置为输出模式

	SDA_L;//将数据线拉低
	SCL_H;//拉高时钟线，使数据有效
	drv_systick_us(5);//>4us，延时5us，满足IIC时序要求
	SDA_H;//拉高数据线，产生上升沿
	drv_systick_us(5);//>4.7us，延时5us，满足IIC时序要求
}
void drv_iic_sendACK(void)
{
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_out();//将数据线设置为输出模式

	SDA_L;//将数据线拉低
	SCL_H;//拉高时钟线，使数据有效
	drv_systick_us(5);//>4us，延时5us，满足IIC时序要求
	SCL_L;//拉低时钟线占用总线
}
void drv_iic_sendNOACK(void)
{
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_out();//将数据线设置为输出模式

	SDA_H;//将数据线拉高
	SCL_H;//拉高时钟线，使数据有效
	drv_systick_us(5);//>4us，延时5us，满足IIC时序要求
	SCL_L;//拉低时钟线占用总线
}
uint8_t drv_iic_waitACK(void)
{
	uint16_t tim_out=0;
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_in();//将数据线设置为输入模式

	SCL_H;//将时钟线拉高，使数据有效
	while(READ_SDA)
	{
		tim_out++;
		if(tim_out>500)
		{
			drv_iic_stop();
			return NOACK;
		}
	}
	SCL_L;//拉低时钟线占用总线
	return ACK;
}
void drv_iic_senddata(uint8_t data)
{
	uint8_t i=0;
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_out();//将数据线设置为输出模式

	for(i=0;i<8;i++)
	{
		if(data&0x80)
		{
			SDA_H;
		}
		else
		{
			SDA_L;
		}
		SCL_H;//将时钟线拉低，使数据无效
		drv_systick_us(1);
		SCL_L;
		drv_systick_us(1);
		data=data<<1;
	}
}
uint8_t drv_iic_readdata(uint8_t flag_ACK)
{
	uint8_t read_data=0,i=0;
	SCL_L;//将时钟线拉低，使数据无效
	drv_iic_in();//将数据线设置为输入模式
	for(i=0;i<8;i++)
	{
		read_data = read_data<<1;
		SCL_H;
		if(READ_SDA)
		{
			read_data|=0x01;
		}
		drv_systick_us(1);
		SCL_L;
		drv_systick_us(1);
	}
	if(flag_ACK == ACK)
	{
		drv_iic_sendACK();
	}
	else
	{
		drv_iic_sendNOACK();
	}
	SCL_L;
	return read_data;
}

